﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using CodeGenerator.Control;
using CodeGenerator.Interface;
using System.Text.RegularExpressions;

namespace CodeGenerator.View
{
    public partial class MainForm : Form
    {
        #region 字段声明
        //声明全局的数据库连接对象
        private static SqlConnection conn = null;
        //创建一个获取数据库连接对象类的实例
        private IConn connSqlServer = null;
        //创建一个获取数据库信息类的实例
        private IGetDatabaseInfo getDatabaseInfo = null;
        //被选中的字段
        private string field = null;
        //消息框内容
        private string msg = string.Empty;
        /// <summary>
        /// 指定表的所有字段及其数据类型
        /// </summary>
        private static DataTable dt = new DataTable();
        /// <summary>
        /// 存储已选的字段及其数据类型
        /// </summary>
        private static DataTable dtSelected = new DataTable();
        #endregion

        public MainForm()
        {
            InitializeComponent();
        }

        private void FmMain_Load(object sender, EventArgs e)
        {
            Binding();
        }
        /// <summary>
        /// 初始化
        /// </summary>
        private void Binding()
        {
            dtSelected.Columns.Add("name");
            dtSelected.Columns.Add("type");
        }

        #region 绑定表名
        /// <summary>
        /// 测试输入的数据库连接信息是否能够连接到制定的数据库
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTryConnect_Click(object sender, EventArgs e)
        {
            connSqlServer=new CConnSqlServer2005();
            getDatabaseInfo = new CGetDatabaseInfoSqlServer2005();

            //数据库连接信息
            string host = cmbHost.Text.Trim();
            string database = cmbDatabase.Text.Trim();
            string userID = cmbUserID.Text.Trim();
            string password = txtPassword.Text.Trim();
            string connStr = "Data Source='" + host + "';;Initial Catalog='" + database + "';Persist Security Info=True;User ID='" + userID + "';Password='" + password + "';";
            if (conn == null)
            {
                //并创建数据库连接对象
                conn = (SqlConnection)connSqlServer.GetConnObj(connStr);
            }
            //声明一个内存表存储指定数据库的所有表名
            DataTable dt = new DataTable();
            try
            {   //获取指定数据库所有表名        
                dt = getDatabaseInfo.GetTableName(database, conn);
                //禁用再次连接
                btnTryConnect.Enabled = false;
                //打开功能
                groupBox2.Enabled = true;
                groupBox3.Enabled = true;
                btnCreatClass.Enabled = true;

                //清空下拉框
                cmbTableName.Text = "";
                cmbTableName.Items.Clear();
                //绑定表名
                BindingTableName(dt);
            }
            catch (SqlException se)
            {
                msg = "数据库登录失败，请检查您输入的信息是否正确！";
                ShowMsg(msg, se.ToString(), MessageBoxIcon.Error);
                //若发生错误禁用功能
                groupBox2.Enabled = false;
                groupBox3.Enabled = false;
                btnCreatClass.Enabled = false;
                conn = null;
            }
            catch (Exception ex)
            {
                msg = "数据库连接遇到未知错误！";
                ShowMsg(msg, ex.ToString(), MessageBoxIcon.Error);
                //若发生错误禁用功能
                groupBox2.Enabled = false;
                groupBox3.Enabled = false;
                btnCreatClass.Enabled = false;
            }      
        
        }
        /// <summary>
        /// 将指定数据库所有表名添加到ComboBox中
        /// </summary>
        /// <param name="dt">表名集合</param>
        private void BindingTableName(DataTable dt)
        {
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                cmbTableName.Items.Add(dt.Rows[i][0].ToString());
            }
        }
        #endregion

        #region 绑定字段
        private void cmbTableName_SelectedIndexChanged(object sender, EventArgs e)
        {
            getDatabaseInfo = new CGetDatabaseInfoSqlServer2005();
            //表名
            string tableName = cmbTableName.Text.Trim();         
            //声明一个内存表存储指定数据库的所有表名
            if (dt == null)
            {
                dt = new DataTable();                
            }
            try
            {
                //获取指定表的所有字段名
                dt = getDatabaseInfo.GetField(tableName, conn);
                //清空
                lisbField.Items.Clear();
                lisbFieldSelected.Items.Clear();
                //将字段名添加到ListBox中
                BindingField(dt);

                groupBox3.Enabled = true;
                btnCreatClass.Enabled = true;
            }
            catch (SqlException se)
            {
                msg = "数据读取有误！";
                ShowMsg(msg, se.ToString(), MessageBoxIcon.Error);

                //若发生错误禁用功能
                groupBox3.Enabled = false;
                btnCreatClass.Enabled = false;
            }
            catch (Exception ex)
            {
                msg = "数据库连接遇到未知错误！";
                ShowMsg(msg, ex.ToString(), MessageBoxIcon.Error);
                //若发生错误禁用功能
                groupBox3.Enabled = false;
                btnCreatClass.Enabled = false;
            }
        }
        /// <summary>
        /// 将指定表中的所有字段名添加到ListBox中
        /// </summary>
        /// <param name="dt">字段名集合</param>
        private void BindingField(DataTable dt)
        {
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                lisbField.Items.Add(dt.Rows[i][0].ToString());
            }
        }
        #endregion

        #region 移动字段
        #region 单项移动
        /// <summary>
        /// 向右移动单项
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMoveRight_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(field) && !CheckFieldIsExist(field, lisbFieldSelected))//已选项不能为空，检测该字段是否存在
            {
                lisbField.Items.Remove(field);
                lisbFieldSelected.Items.Add(field);
                AddFieldToDtSelected(field);
                field = null;                
            }
        }
       

        /// <summary>
        /// 向左移动单项
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMoveLeft_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(field) && !CheckFieldIsExist(field, lisbField))//已选项不能为空，检测该字段是否存在
            {
                lisbFieldSelected.Items.Remove(field);
                lisbField.Items.Add(field);

                RemoveFieldFromDtSelected(field);
                field = null;
            }
        } 
        /// <summary>
        /// 从已选字段内存表中移除选中的行，并添加该行指dt内存表中
        /// </summary>
        /// <param name="str">已选字段名</param>
        private void RemoveFieldFromDtSelected(string str)
        {
            int i = dtSelected.Rows.Count;
             do
             {
                 i--;
                 if (dtSelected.Rows[i][0].ToString() == str)
                 {
                     object[] obj = new object[2];
                     obj[0] = dtSelected.Rows[i][0].ToString();
                     obj[1] = dtSelected.Rows[i][1].ToString();
                     dt.Rows.Add(obj);//移除dt中的行
                     dtSelected.Rows.Remove(dtSelected.Rows[i]);//添加到dtSelected中
                     return;
                 }

             } while (i > 0);//从顶至底搜索已选项，并移除和添加
        }
       
        /// <summary>
        /// 从dt中移除选中行，并添加到已选字段内存表中
        /// </summary>
        /// <param name="str">已选字段</param>
        private void AddFieldToDtSelected(string str)
        {
            if (dtSelected == null)
            {
                dtSelected = new DataTable();
            }           
           int i = dt.Rows.Count;
           do
           {
               i--;
               if (dt.Rows[i][0].ToString() == str)
               {
                   object[] obj = new object[2];
                   obj[0] = dt.Rows[i][0].ToString();
                   obj[1] = dt.Rows[i][1].ToString();

                   dtSelected.Rows.Add(obj);
                   dt.Rows.Remove(dt.Rows[i]);
                   return;
               }
           } while (i > 0);//从顶至底搜索已选项，并移除和添加
        }
        
        /// <summary>
        /// 字段单选时检查该字段是否已存在
        /// </summary>
        /// <param name="str">字段名</param>
        /// <param name="lisb">ListBox</param>
        /// <returns>是否存在</returns>
        private bool CheckFieldIsExist(string str, ListBox lisb)
        {
            object[] objs = new object[lisb.Items.Count];
            lisb.Items.CopyTo(objs, 0);//将ListBox中的值存入object数组中
            foreach (object obj in objs)
            {
                if (obj.ToString() == str)
                {
                    return true;//存在则跳出
                }
                else
                {
                    continue;//不存在则继续遍历循环
                }
            }
            return false;
        } 
       
        #endregion

        #region 移动全部
        /// <summary>
        /// 向右移动全部项按钮单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAllMoveRight_Click(object sender, EventArgs e)
        {            
            MoveAllRight();

            if (dtSelected == null)
            {
                dtSelected = new DataTable();        
            }
            //内存表数据移动
            if (dt != null)
            {
                AddFieldToDtSelected();
            }            
        }
        /// <summary>
        /// 向右移动全部项
        /// </summary>
        private void MoveAllRight()
        {
            object[] objs = new object[lisbField.Items.Count];
            lisbField.Items.CopyTo(objs, 0);
            //lisb中数据移动
            foreach (object obj in objs)
            {
                lisbField.Items.Remove(obj.ToString());
                lisbFieldSelected.Items.Add(obj.ToString());
            }
        }
        /// <summary>
        /// 从dt中移除所有行，并添加到已选字段内存表中
        /// </summary>
        private void AddFieldToDtSelected()
        {
            if (dtSelected == null)
            {
                dtSelected = new DataTable();
            }
            int i = dt.Rows.Count;
            do
            {
                try
                {
                    i--;
                    object[] obj = new object[2];
                    obj[0] = dt.Rows[i][0].ToString();
                    obj[1] = dt.Rows[i][1].ToString();

                    dtSelected.Rows.Add(obj);
                    dt.Rows.Remove(dt.Rows[i]);
                }
                catch (IndexOutOfRangeException ix)
                {
                    msg = "没有可移动的项！";
                    ShowMsg(msg, ix.ToString(), MessageBoxIcon.Error);
                    return;
                }
            } while (i > 0);//从顶至底移动数据
        }
        /// <summary>
        /// 向左移动全部项按钮单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAllMoveLeft_Click(object sender, EventArgs e)
        {
            MoveAllLeft();

            //内存表数据移动
            if (dtSelected != null)
            {
                RemoveFieldFromDtSelected();
            }
        
        }
        /// <summary>
        /// 向左移动全部项
        /// </summary>
        private void MoveAllLeft()
        {
            object[] objs = new object[lisbFieldSelected.Items.Count];
            lisbFieldSelected.Items.CopyTo(objs, 0);
            //Lisb中数据移动
            foreach (object obj in objs)
            {
                lisbFieldSelected.Items.Remove(obj.ToString());
                lisbField.Items.Add(obj.ToString());
            }
        }
        /// <summary>
        /// 从已选字段内存表中移除所有的行，并添加至dt内存表中
        /// </summary>
        private void RemoveFieldFromDtSelected()
        {
            int i = dtSelected.Rows.Count;
            do
            {
                try
                {
                    i--;
                    object[] obj = new object[2];
                    obj[0] = dtSelected.Rows[i][0].ToString();
                    obj[1] = dtSelected.Rows[i][1].ToString();
                    dt.Rows.Add(obj);//移除dt中的行
                    dtSelected.Rows.Remove(dtSelected.Rows[i]);//添加到dtSelected中 
                }
                catch (IndexOutOfRangeException ix)
                {
                    msg = "没有可移动的项！";
                    ShowMsg(msg, ix.ToString(), MessageBoxIcon.Error);
                    return;
                }
            } while (i > 0);//从顶至底移动数据
 
        }
        #endregion
        /// <summary>
        /// 选中的字段
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lisbField_Click(object sender, EventArgs e)
        {
            try
            {
                field = lisbField.SelectedItem.ToString(); 
            }
            catch
            { }
        }
        /// <summary>
        /// 选中的字段
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lisbFieldSelected_Click(object sender, EventArgs e)
        {
            try
            {
                field = lisbFieldSelected.SelectedItem.ToString();
            }
            catch 
            { }
        }       

        
        #endregion

        #region 创建实体类
        /// <summary>
       /// 创建实体类
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
        private void btnCreatClass_Click(object sender, EventArgs e)
        {
            string path = @System.Windows.Forms.Application.StartupPath + "\\EntityClass\\";//路径
            if (!Check())
            {
                return;
            }
            //生成代码
            ICreatEntityClass creatEntityClass = new CCreatEntityClass();
            string strCode = creatEntityClass.CreatEntityClass(cmbTableName.Text.Trim(), dtSelected, txtClassName.Text.Trim(), txtNamespace.Text.Trim());
            //写入.cs文件
            if (creatEntityClass.CreatEntityClassFile(txtClassName.Text.Trim(), strCode, path))
            {
                ShowMsg("实体类创建成功！", null, MessageBoxIcon.Information);
            }

        }
        /// <summary>
        /// 生成实体类前对相关数据进行验证
        /// </summary>
        /// <returns>验证是否通过</returns>
        private bool Check()
        {
            string msg = string.Empty;
            Regex reg = null;
             //未选择字段
            if (lisbFieldSelected.Items.Count < 1)
            {
                msg = "请选择字段！";
                ShowMsg(msg, null, MessageBoxIcon.Information);
                lisbField.Focus();
                return false;
            }//未填写类名
            if (String.IsNullOrEmpty(txtClassName.Text.Trim()))
            {
                msg = "请填写类名";
                ShowMsg(msg, null, MessageBoxIcon.Information);
                txtClassName.Focus();
                return false;
            }
            //实体类名命名验证
            reg = new Regex(@"^[a-zA-Z|_]{1,}[a-zA-Z0-9|_]{0,}$");//正则表达式，定义类名和命名空间的命名规则
            if (!reg.IsMatch(txtClassName.Text.Trim()))
            {
                msg = "类名第一个字符必须为字母，且不可包含除字母，数字和 _ 外的字符！";
                ShowMsg(msg, null, MessageBoxIcon.Information);
                txtClassName.Focus();
                return false;
            }           
            //未填写命名空间
            if (String.IsNullOrEmpty(txtNamespace.Text.Trim()))
            {
                msg = "请填写命名空间！";
                ShowMsg(msg, null, MessageBoxIcon.Information);
                txtNamespace.Focus();
                return false;
            }
            //命名空间命名验证
            reg = new Regex(@"^[a-zA-Z|_]{1,}[a-zA-Z0-9|_|.]{0,}$");
            if(!reg.IsMatch(txtNamespace.Text.Trim()))
            {
                msg = "命名空间第一个字符必须为字母，且不可包含除字母，数字, _ 和 . 外的字符！";
                ShowMsg(msg, null, MessageBoxIcon.Information);
                txtNamespace.Focus();
                return false;
            }
           
           
            return true;
        }

        
        #endregion
        /// <summary>
        /// 自定义消息框
        /// </summary>
        /// <param name="msg">消息</param>
        /// <param name="ex">错误信息</param>
        /// <param name="msgIco">消息框标志类型</param>
        private void ShowMsg(string msg,string ex,MessageBoxIcon msgIco)
        {
            if (ex != null)
            {
                ex = "\r\n" + ex;
            }
            switch (msgIco)
            {
                case MessageBoxIcon.Information:
                    MessageBox.Show(msg+ex, "提示", MessageBoxButtons.OK, msgIco);
                    break;
                case MessageBoxIcon.Warning:
                    MessageBox.Show(msg+ex, "警告", MessageBoxButtons.OK, msgIco);
                    break;
                case MessageBoxIcon.Error:
                    MessageBox.Show(msg + ex, "错误", MessageBoxButtons.OK, msgIco);
                    break;
                default:
                    MessageBox.Show(msg + ex, "提示", MessageBoxButtons.OK, msgIco);
                    break;
            }
        }
        /// <summary>
        /// 退出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Dispose();
        }

    }
}
